home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Commun⁄Network / NewsWatcher 2.0d17 Source / source / smtp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-10  |  6.5 KB  |  251 lines  |  [TEXT/KAHL]

  1. /*----------------------------------------------------------------------------
  2.  
  3.     smtp.c
  4.  
  5.     This module handles all transactions with SMTP servers.
  6.     
  7.     Portions copyright © 1990, Apple Computer.
  8.     Portions copyright © 1993, Northwestern University.
  9.  
  10. ----------------------------------------------------------------------------*/
  11.  
  12. #include <stdlib.h>
  13. #include <string.h>
  14.  
  15. #include "MacTCPCommonTypes.h"
  16. #include "TCPPB.h"
  17.  
  18. #include "glob.h"
  19. #include "dlgutil.h"
  20. #include "smtp.h"
  21. #include "tcp.h"
  22. #include "util.h"
  23. #include "log.h"
  24.  
  25.  
  26. /* global variables */
  27.  
  28. static char *gBuffer;     /* RecvData buffer */
  29.  
  30.  
  31.  
  32. /*  GetSMTPAddr is called to get the mail server IP address,
  33.     given its name from the preferences file.
  34. */
  35.  
  36. static Boolean GetSMTPAddr (unsigned long *addr)
  37. {
  38.     OSErr err;
  39.     
  40.     p2cstr(gPrefs.mailServerName);
  41.     err = IPNameToAddr((char*)gPrefs.mailServerName, addr);
  42.     c2pstr((char*)gPrefs.mailServerName);
  43.     if (err != noErr) {
  44.         if (err != -1) ErrorMessage("Could not get mail server address.");
  45.         return false;
  46.     }
  47.     return true;
  48. }
  49.  
  50.  
  51. /*    RcptMsg determines the recipients of the message and sends commands
  52.     to the SMTP server specifying these people as recipients.
  53. */
  54.  
  55. static Boolean RcptMsg (char *text, unsigned short tLength, 
  56.     unsigned long stream, char *header)
  57. {
  58.     Ptr current,current2,current3,lineEnd,textEnd;
  59.     CStr255 sendData[4];
  60.     unsigned short length,hdrLen,len;
  61.     Boolean foundHeader;
  62.     OSErr err;
  63.     
  64.     strcpy(sendData[0],"RCPT TO:<");
  65.     strcpy(sendData[2],">");
  66.     strcpy(sendData[3],CRLF);
  67.  
  68.     /* Find the header line. */
  69.     
  70.     current = text;
  71.     hdrLen = strlen(header);
  72.     textEnd = text + tLength;
  73.     foundHeader = false;
  74.     while (!foundHeader && current < textEnd && *current != CR) {
  75.         if (strncasecmp(current,header,hdrLen) == 0) {
  76.             foundHeader = true;
  77.         } else {
  78.             while (current < textEnd && *current != CR) current++;
  79.             current += 2;
  80.         }
  81.     }
  82.     if (!foundHeader) return true;
  83.     
  84.     /* Find the end of the header line. */
  85.     
  86.     current += hdrLen;
  87.     if (current >= textEnd) return true;
  88.     for (lineEnd = current; lineEnd < textEnd && *lineEnd != CR; lineEnd++);
  89.     if (lineEnd >= textEnd) return true;
  90.     
  91.     /* Send a RCPT TO command for each address in the header line.
  92.        Addresses are delimited by commas, and may be in any of the
  93.        forms specified in RFC 1036:
  94.        
  95.                addr
  96.             addr (name)
  97.             name <addr>
  98.     */
  99.     
  100.     while (current < lineEnd) {
  101.         while (current < lineEnd && *current == ' ') current++;
  102.         current2 = current;
  103.         while (current2 < lineEnd && *current2 != ',') current2++;
  104.         current3 = current2 - 1;
  105.         while (current3 > current && *current3 == ' ') current3--;
  106.         if (current3 > current) {
  107.             if (*current3 == ')') {
  108.                 current3--;
  109.                 while (current3 > current && *current3 != '(') current3--;
  110.                 current3--;
  111.                 while (current3 > current && *current3 == ' ') current3--;
  112.             } else if (*current3 == '>') {
  113.                 current3--;
  114.                 while (current3 > current && *current3 == ' ') current3--;
  115.                 while (current < current3 && *current != '<') current++;
  116.                 current++;
  117.                 while (current < current3 && *current == ' ') current++;
  118.             }
  119.         }
  120.         len = current3 - current + 1;
  121.         if (len > 0 && len < 255) {
  122.             strncpy(sendData[1], current, len);
  123.             sendData[1][len] = 0;
  124.             if ((err = SendMultiData(stream,sendData,4)) != noErr) goto exit1;
  125.             length = kBufLen;
  126.             if ((err = RecvData(stream,gBuffer,&length,true)) != noErr) goto exit1;
  127.             if (length < 3 || *gBuffer != '2') goto exit2;
  128.         }
  129.         current = current2 + 1;
  130.     }
  131.     
  132.     return true;
  133.  
  134. exit1:
  135.  
  136.     UnexpectedErrorMessage(err);
  137.     return false;
  138.     
  139. exit2:
  140.  
  141.     MailOrFTPServerErrorMessage(gBuffer);
  142.     return false;
  143.     
  144. }
  145.  
  146.  
  147. /*    SendSMTP sends a message through e-mail by contacting the local
  148.     SMTP server and sending the mail.
  149. */
  150.  
  151. Boolean SendSMTP (char *text,unsigned short tLength)
  152. {
  153.     unsigned long stream = 0;
  154.     unsigned short length;
  155.     CStr255 sendData[4];
  156.     unsigned long addr;
  157.     CStr255 commStr;
  158.     OSErr err;
  159.     char *serverCommand = nil;
  160.     
  161.     gBuffer = nil;
  162.     gBuffer = NewPtrClear(kBufLen);
  163.     if ((err = MyMemErr()) != noErr) goto exit1;
  164.     
  165.     if (!GetSMTPAddr(&addr)) goto exit1;
  166.         
  167.     if ((err = CreateStream(&stream,kBufLen)) != noErr) goto exit1;
  168.     if ((err = OpenConnection(stream,addr,kSMTPPort,20)) != noErr) {
  169.         if (err != -1) ErrorMessage("Could not open connection to mail server.");
  170.         goto exit3;
  171.     }
  172.         
  173.     length = kBufLen;
  174.     if ((err = RecvData(stream,gBuffer,&length,true)) != noErr) goto exit1;
  175.     if (length < 3 || *gBuffer != '2') goto exit2;
  176.     
  177.     strcpy(sendData[0],"HELO ");
  178.     if ((err = GetMyIPName(sendData[1])) != noErr) {
  179.         if ((err = GetMyIPAddrStr(sendData[1])) != noErr) goto exit1;
  180.     }
  181.     strcpy(sendData[2],CRLF);
  182.     serverCommand = "HELO";
  183.     if ((err = SendMultiData(stream,sendData,3)) != noErr) goto exit1;
  184.     length = kBufLen;
  185.     if ((err = RecvData(stream,gBuffer,&length,true)) != noErr) goto exit1;
  186.     if (length < 3 || *gBuffer != '2') goto exit2;
  187.     
  188.     strcpy(sendData[0],"MAIL FROM:<");
  189.     strcpy(sendData[1],gPrefs.address);
  190.     strcpy(sendData[2],">");
  191.     strcpy(sendData[3],CRLF);
  192.     serverCommand = "MAIL FROM";
  193.     if ((err = SendMultiData(stream,sendData,4)) != noErr) goto exit1;
  194.     length = kBufLen;
  195.     if ((err = RecvData(stream,gBuffer,&length,true)) != noErr) goto exit1;
  196.     if (length < 3 || *gBuffer != '2') goto exit2;
  197.     
  198.     if (!RcptMsg(text,tLength,stream,"To: ")) goto exit3;
  199.     if (!RcptMsg(text,tLength,stream,"Cc: ")) goto exit3;
  200.     if (!RcptMsg(text,tLength,stream,"Bcc: ")) goto exit3;
  201.     
  202.     strcpy(commStr,"DATA");
  203.     strcat(commStr,CRLF);
  204.     serverCommand = "DATA";
  205.     if ((err = SendData(stream,commStr,6)) != noErr) goto exit1;
  206.     length = kBufLen;
  207.     if ((err = RecvData(stream,gBuffer,&length,true)) != noErr) goto exit1;
  208.     if (length < 3 || *gBuffer != '3') goto exit2;
  209.  
  210.     if (gPrefs.logActionsToFile) LogMailMessage(text, tLength);
  211.     if ((err = SendData(stream,text,tLength)) != noErr) goto exit1;
  212.     strcpy(commStr,CRLF);
  213.     strcat(commStr,".");
  214.     strcat(commStr,CRLF);
  215.     if ((err = SendData(stream,commStr,5)) != noErr) goto exit1;
  216.     length = kBufLen;
  217.     if ((err = RecvData(stream,gBuffer,&length,true)) != noErr) goto exit1;
  218.     if (length < 3 || *gBuffer != '2') goto exit2;
  219.     
  220.     strcpy(commStr,"QUIT");
  221.     strcat(commStr,CRLF);
  222.     serverCommand = "QUIT";
  223.     if ((err = SendData(stream,commStr,6)) != noErr) goto exit1;
  224.     length = kBufLen;
  225.     if ((err = RecvData(stream,gBuffer,&length,true)) != noErr) goto exit1;
  226.     if (length < 3 || *gBuffer != '2') goto exit2;
  227.     
  228.     if ((err = CloseConnection(stream, true)) != noErr) goto exit1;
  229.     if ((err = ReleaseStream(stream)) != noErr) goto exit1;
  230.     MyDisposPtr(gBuffer);
  231.     return true;
  232.     
  233. exit1:
  234.  
  235.     UnexpectedErrorMessage(err);
  236.     goto exit3;
  237.     
  238. exit2:
  239.  
  240.     MailOrFTPServerErrorMessage(gBuffer);
  241.  
  242. exit3:
  243.  
  244.     if (stream != 0) {
  245.         AbortConnection(stream);
  246.         ReleaseStream(stream);
  247.     }
  248.     MyDisposPtr(gBuffer);
  249.     return false;
  250. }
  251.